use std::sync::Arc;
use std::time::Duration;
use tokio::sync::RwLock;

#[derive(Debug)]
pub struct Metrics {
    pub messages_processed: u64,
    pub messages_queued: u64,
    pub messages_dropped: u64,
    pub avg_processing_time: Duration,
    pub avg_queuing_time: Duration,
    pub errors: u64,
    pub status_changes: u64,
}

impl Metrics {
    pub fn new() -> Self {
        Self {
            messages_processed: 0,
            messages_queued: 0,
            messages_dropped: 0,
            avg_processing_time: Duration::new(0, 0),
            avg_queuing_time: Duration::new(0, 0),
            errors: 0,
            status_changes: 0,
        }
    }

    pub fn record_message_processing(&mut self, duration: Duration) {
        self.messages_processed += 1;
        // Update average processing time logic here
    }

    pub fn record_failure(&mut self) {
        self.messages_dropped += 1;
        self.errors += 1;
    }
} 
pub struct ProtoMetrics {
    providers: Vec<Box<dyn MetricsProvider>>,
    actor_stats: Arc<RwLock<ActorStats>>,
}

impl ProtoMetrics {
    pub fn new(providers: Vec<Box<dyn MetricsProvider>>) -> Self {
        Self {
            providers,
            actor_stats: Arc::new(RwLock::new(ActorStats::default())),
        }
    }

    pub async fn record_message_received(&self, actor_type: &str) {
        let mut stats = self.actor_stats.write().await;
        stats.messages_received += 1;
        
        for provider in &self.providers {
            provider.record_message(actor_type, "received");
        }
    }

    pub async fn record_actor_spawned(&self, actor_type: &str) {
        let mut stats = self.actor_stats.write().await;
        stats.actors_spawned += 1;
        
        for provider in &self.providers {
            provider.record_actor_spawned(actor_type);
        }
    }
}

#[async_trait::async_trait]
pub trait MetricsProvider: Send + Sync {
    async fn record_message(&self, actor_type: &str, message_type: &str);
    async fn record_actor_spawned(&self, actor_type: &str);
    async fn record_actor_stopped(&self, actor_type: &str);
}

#[derive(Default)]
pub struct ActorStats {
    pub messages_received: u64,
    pub messages_sent: u64,
    pub actors_spawned: u64,
    pub actors_stopped: u64,
}
